// ====================CardSprite====================

class Sprite_Card extends Sprite {
    initialize(opts) {
        this._opts = opts;
        super.initialize();
        this._moveAnimation = null;
        this._scaleAnimation = null;
        this._blurAnimation = null;
        this._turnAnimation = null;
        this._hideDelay = -1;
        this._moving = false;
        this.createAllSprite();
        this.scale.set(SDS_CARD_PLUGIN_PARAM.cardLayout.cardScaleX, SDS_CARD_PLUGIN_PARAM.cardLayout.cardScaleY);
        this.anchor.set(0.5, 1);
    }

    createAllSprite() {
        this.createCardOverlay();
        this.createCardBackSprite();
        this.createCardFaceSprite();
    }

    createCardOverlay() {
        const fileName = SDS_CARD_PLUGIN_PARAM.cardLayout.highlighterLayerFile;
        this.bitmap = ImageManager.loadSystem(fileName);
        this.bitmap.addLoadListener(() => {
            const {width, height} = this.bitmap;
            this.setPopular();
        })
        // this.addChild(sprite);
        // this._overlaySprite = sprite;
    }

    createCardBackSprite() {
        const {width, height, r, rim} = this._opts;
        let bitmap;
        // TODO 用图片或者绘制
        if (true) {
            const fileName = SDS_CARD_PLUGIN_PARAM.cardLayout.cardFaceLayerFile;
            bitmap = ImageManager.loadSystem(fileName);
            bitmap._smooth = false;
            bitmap._updateScaleMode();
        } else {
            const describeRect = SDS_CARD_PLUGIN_PARAM.cardLayout.describeRect;
            bitmap = new Bitmap(width, height);
            // 绘制背景
            bitmap.fillRoundRect(rim, rim, this.width - 2 * rim, this.height - 2 * rim, "#FFFFFF", r);
            bitmap.fillRoundRect(2 * rim, 2 * rim, this.width - 4 * rim, this.height - 4 * rim, "#E0C9A1", r - rim);
            bitmap.fillRoundRect(describeRect.x, describeRect.y, describeRect.width, describeRect.height, "#de8320", r - rim);
        }
        const sprite = new Sprite(bitmap);
        sprite.move(0, -19);
        sprite.anchor.set(0.5, 1);
        this.addChild(sprite);
        this._backSprite = sprite;
    }

    createCardFaceSprite() {
        const {width, height, r, rim} = this._opts;
        const bitmap = new Bitmap(width, height);
        const sprite = new Sprite(bitmap);
        sprite.anchor.set(0.5, 1);
        sprite.move(0, -19);
        bitmap.outlineWidth = 0;
        // bitmap.fontBold = true;
        bitmap.fontFace = $gameSystem.mainFontFace();
        this.addChild(sprite);
        this._cardFaceSprite = sprite;
    }

    drawCardFace() {
        const bitmap = this._cardFaceSprite.bitmap;
        bitmap.clear();
        bitmap._smooth = false;
        bitmap._updateScaleMode();
        // 绘制费用
        this.drawCardCost();
        // 绘制图像
        this.drawCardImage();
        // 绘制卡牌名称
        this.drawCardName();
        // 绘制技能描述
        this.drawCardDescribe();
        // 绘制卡牌类型
        this.drawCardType();
    }

    drawCardCost() {
        const bitmap = this._cardFaceSprite.bitmap;
        const costRect = SDS_CARD_PLUGIN_PARAM.cardLayout.costRect;
        const cost = this.object().cost();
        const iconIndex = 164;
        const iconWidth = 16
        let x = costRect.x;
        let y = costRect.y + (costRect.height - iconWidth) / 2;
        for (let i = 0; i < cost; i++) {
            bitmap.drawIcon(iconIndex, x, y, iconWidth, iconWidth);
            x += iconWidth + 2;
        }
    }

    drawCardImage() {
        const bitmap = this._cardFaceSprite.bitmap;
        const card = this.object();
        const fileName = $dataCards[card?.id()]?.image;
        const imageRect = SDS_CARD_PLUGIN_PARAM.cardLayout.imageRect;
        // 图片设置了则绘制图像，否则绘制技能图标
        if (!!fileName) {
            const imageBitmap = ImageManager.loadCard(fileName);
            imageBitmap.addLoadListener(() => {
                bitmap.blt(imageBitmap, 0, 0, imageBitmap.width, imageBitmap.height, imageRect.x, imageRect.y, imageRect.width, imageRect.height);
            })
        } else {
            const iconIndex = $dataSkills[card?.skillId() || 0]?.iconIndex || 0;
            bitmap.drawIcon(iconIndex, imageRect.x, imageRect.y, imageRect.width, imageRect.height);
        }
    }

    drawCardName() {
        const bitmap = this._cardFaceSprite.bitmap;
        const name = this.object().name();
        const nameRect = SDS_CARD_PLUGIN_PARAM.cardLayout.nameRect;
        bitmap.fontSize = 20;
        bitmap.textColor = "#ffffff";
        bitmap.drawText(name, nameRect.x, nameRect.y, nameRect.width, nameRect.height, "center");
    }

    drawCardDescribe() {
        const bitmap = this._cardFaceSprite.bitmap;
        const description = this.object().description();
        const describeRect = SDS_CARD_PLUGIN_PARAM.cardLayout.describeRect;
        bitmap.fontSize = 14;
        bitmap.textColor = "#000000";
        bitmap.drawTextPlus(description, describeRect.x, describeRect.y, describeRect.width + 15, describeRect.height);
    }

    drawCardType() {
        const bitmap = this._cardFaceSprite.bitmap;
        const types = this.object().type();
        const typeRect = SDS_CARD_PLUGIN_PARAM.cardLayout.typeRect;
        let typeText = "";
        bitmap.fontSize = 12;
        bitmap.textColor = "#000000";
        for (const type of types) {
            typeText += `<${type}>`;
        }
        bitmap.drawText(typeText, typeRect.x, typeRect.y, typeRect.width, typeRect.height, "right");
    }

    hide(delay = 0) {
        if (!delay) {
            super.hide();
        } else {
            this._hideDelay = delay;
        }
    }

    show() {
        super.show();
        this.scale.set(SDS_CARD_PLUGIN_PARAM.cardLayout.cardScaleX, SDS_CARD_PLUGIN_PARAM.cardLayout.cardScaleY);
        this.opacity = 255;
    }

    /**
     * 设为普通
     */
    setPopular() {
        const {width, height} = this.bitmap;
        this.setFrame(0, 0, width / 2, height);
    }

    /**
     * 设为焦点
     */
    setFocus() {
        const {width, height} = this.bitmap;
        this.setFrame(width / 2, 0, width / 2, height);
    }

    /**
     * 设置原始坐标
     * @param ox
     * @param oy
     * @param or
     */
    setOriginPoint(ox, oy, or = 0) {
        this._ox = ox;
        this._oy = oy;
        this._or = or;
        this.cloneOriginWorldTransform();
    }

    /**
     * 克隆世界变换矩阵，作为手牌触摸检测判定用
     */
    cloneOriginWorldTransform() {
        // 记录当前位置
        const {x, y} = this;
        // 先移动到原点计算原点矩阵
        this.move(this._ox, this._oy);
        // 刷新变换矩阵，需要手动刷新，否则会慢1帧导致位置判断出错
        this.updateTransform();
        // 克隆矩阵
        this._originWorldTransform = this.worldTransform.clone();
        // 还原位置
        this.move(x, y);
    }

    /**
     * 设置原始z层级
     * @param oz
     */
    setOriginZIndex(oz) {
        this._oz = oz;
    }

    /**
     * 对象
     * @returns {Game_Card} 卡牌
     */
    object() {
        return this._object;
    }

    setObject(card) {
        this._object = card;
        // TODO 临时记录下id
        this._cardId = card.id();
        this.drawCardFace();
    }

    hitTest() {
        const matrix = this._originWorldTransform ?? this.worldTransform;
        const touchPos = new Point(TouchInput.x, TouchInput.y);
        // const localPos = this.worldTransform.applyInverse(touchPos);
        const localPos = matrix.applyInverse(touchPos);
        const rect = new Rectangle(
            -this.anchor.x * this.width,
            -this.anchor.y * this.height,
            this.width,
            this.height
        );
        return rect.contains(localPos.x, localPos.y);
    }

    /**
     * 判断是否在动画中
     */
    isAnimation() {
        return !!this._moveAnimation || !!this._scaleAnimation || !!this._blurAnimation;
    }

    /**
     * 设置移动动画
     * @param {number} x 目标点x坐标
     * @param {number} y 目标点y坐标
     * @param {number} d 移动持续时长
     */
    setMoveAnimation(x, y, duration = 20, delay = 0) {
        this._moveAnimation = {x, y, duration, delay};
    }

    /**
     * 设置缩放动画
     * @param {number} x 最终的x缩放倍率
     * @param {number} y 最终的y缩放倍率
     * @param {number} duration 缩放持续时长
     */
    setScaleAnimation(x, y, duration = 20) {
        x *= SDS_CARD_PLUGIN_PARAM.cardLayout.cardScaleX;
        y *= SDS_CARD_PLUGIN_PARAM.cardLayout.cardScaleY;
        this._scaleAnimation = {x, y, duration};
    }

    /**
     * 设置x虚化动画
     * @param {number} opacity 最终的不透明度
     * @param {number} duration 虚化持续时长
     */
    setBlurAnimation(opacity, duration = 20) {
        this._blurAnimation = {opacity, duration};
    }

    /**
     * 清空所有动画
     */
    clearAnimation() {
        this._moveAnimation = null;
        this._scaleAnimation = null;
        this._blurAnimation = null;
        this._turnAnimation = null;
    }

    update() {
        super.update();
        this.updateAnimation();
        this.updateHide();
    }

    updateAnimation() {
        if (!!this._moveAnimation) this.updateMoveAnimation();
        if (!!this._scaleAnimation) this.updateScaleAnimation();
        if (!!this._blurAnimation) this.updateBlurAnimation();
    }

    /**
     * 更新移动动画
     */
    updateMoveAnimation() {
        const {x, y, duration, delay} = this._moveAnimation;
        if (delay > 0) {
            this._moveAnimation.delay--;
            return;
        }
        if (duration <= 0) {
            this._moveAnimation = null;
            return;
        }
        const tx = Math.round((this.x * (duration - 1) + x) / duration);
        const ty = Math.round((this.y * (duration - 1) + y) / duration);
        this.move(tx, ty);
        this._moveAnimation.duration--;
    }

    /**
     * 更新缩放动画
     */
    updateScaleAnimation() {
        const {x, y, duration} = this._scaleAnimation;
        if (duration <= 0) {
            this._scaleAnimation = null;
            return;
        }
        const sx = (this.scale.x * (duration - 1) + x) / duration;
        const sy = (this.scale.y * (duration - 1) + y) / duration;
        this.scale.set(sx, sy);
        this._scaleAnimation.duration--;
    }

    /**
     * 更新虚化动画
     */
    updateBlurAnimation() {
        const {opacity, duration} = this._blurAnimation;
        if (duration <= 0) {
            this._blurAnimation = null;
            return;
        }
        const to = Math.round((this.opacity * (duration - 1) + opacity) / duration);
        // console.log(to)
        this.opacity = to;
        this._blurAnimation.duration--;
    }

    /**
     * 更新隐藏
     */
    updateHide() {
        if (this._hideDelay < 0) return;
        if (this._hideDelay === 0) {
            super.hide();
        }
        this._hideDelay--;
    }
}